﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XmlStudio.DataLayer;
using XmlStudio.Interfaces;
using System.Windows.Input;
using System.Windows.Data;
using WPFExtensions.ViewModel.Commanding;
using System.Windows;
using System.Windows.Controls;

namespace XmlStudio.ViewModel {
    /// <summary>
    /// Context menu helper.
    /// </summary>
    class XsdContextMenu {
        //private static IInputElement target_;

        private static void AddSharedItems(ContextMenu menu) {
            menu.Items.Add(Application.Current.TryFindResource("EditXsdSharedMenuItem") as MenuItem);
            menu.Items.Add(Application.Current.TryFindResource("RemoveNodeSharedMenutItem") as MenuItem);
            menu.Items.Add(Application.Current.TryFindResource("ExpandWithSubtreeSharedMenuItem") as MenuItem);
            menu.Items.Add(Application.Current.TryFindResource("ChangeBackgroundSharedMenuItem") as MenuItem);
            menu.Items.Add(Application.Current.TryFindResource("ChangeAppearanceSharedMenuItem") as MenuItem);
            menu.Items.Add(Application.Current.TryFindResource("SelectSubtreeForCopyingMenuItem") as MenuItem);
            menu.Items.Add(Application.Current.TryFindResource("SelectSubtreeForMovingMenuItem") as MenuItem);
            menu.Items.Add(Application.Current.TryFindResource("PasteSubtreeMenuItem") as MenuItem);
            menu.Items.Add(Application.Current.TryFindResource("AddChildXsdElementSharedMenuItem") as MenuItem);
        }

        /// <summary>
        /// Creates the context menu.
        /// </summary>
        /// <param name="elementType">Type of the element.</param>
        /// <param name="parentType">Type of the parent.</param>
        /// <param name="element">The element.</param>
        /// <param name="target">The target.</param>
        /// <returns></returns>
        public static ContextMenu CreateContextMenu(XsdElement elementType, XsdElement? parentType, BigXmlNode element, IInputElement target) {
            var availableContent = XsdStructure.GetContent(elementType, parentType);
            var contextMenu = new ContextMenu();
            AddSharedItems(contextMenu);

            if(availableContent != null) {
                var flatten = FlattenGroups(availableContent).Distinct(new XsdStructureItemEqualityComparer()).OrderBy(x => x.ElementType);

                var menu = new List<MenuItem>();

                var last = contextMenu.Items[contextMenu.Items.Count - 1] as MenuItem;
                foreach(var i in flatten) {
                    last.Items.Add(GetMenuItem(i, element, target));
                }

                //foreach(var item in availableContent) {
                //    if(item is XsdStructureGroup) {
                //        var group = item as XsdStructureGroup;
                //        var groupMenuItem = GetItemsFromGroup(group, element);
                //        last.Items.Add(groupMenuItem);
                //    } else {
                //        last.Items.Add(GetMenuItem(item, element));
                //    }
                //}

                //CommandManager.InvalidateRequerySuggested();
                return contextMenu;
            } else {
                return contextMenu;
            }
        }

        class XsdStructureItemEqualityComparer : IEqualityComparer<XsdStructureItem> {
            public bool Equals(XsdStructureItem x, XsdStructureItem y) {
                if(x == null || y == null) {
                    return false;
                }

                return (x.ElementType.Equals(y.ElementType));
            }

            public int GetHashCode(XsdStructureItem obj) {
                return obj.ElementType.GetHashCode();
            }
        }

        private static IEnumerable<XsdStructureItem> FlattenGroups(IEnumerable<XsdStructureItem> items) {
            var result = new List<XsdStructureItem>();
            foreach(var item in items) {
                if(item is XsdStructureGroup) {
                    var group = item as XsdStructureGroup;
                    var flattenItems = FlattenGroups(group.Items);
                    result.AddRange(flattenItems);
                } else {
                    result.Add(item);
                }
            }

            return result;
        }

        private static MenuItem GetItemsFromGroup(XsdStructureGroup group, BigXmlNode element, IInputElement target) {
            var menuItem = new MenuItem { Header = "group", CommandTarget = target, Tag = "Generated" };
            foreach(var item in group.Items) {
                if(item is XsdStructureGroup) {
                    var groupItem = GetItemsFromGroup(item as XsdStructureGroup, element, target);
                    menuItem.Items.Add(groupItem);
                } else {
                    menuItem.Items.Add(GetMenuItem(item, element, target));
                }
            }

            return menuItem;
        }

        private static MenuItem GetMenuItem(XsdStructureItem item, BigXmlNode element, IInputElement target) {
            return new MenuItem() {
                Header = item.ElementType.ToString(),
                Command = XsdViewModel.CreateXsdElementCommand,
                CommandParameter = new CreateXsdElementParam { Node = element, ElementType = item.ElementType },
                CommandTarget = target,
                Tag = "Generated"
            };
        }
    }
}
